/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ijkplayer_napi_render.h"

const int32_t STR_DEFAULT_SIZE = 1024;
const int32_t INDEX_0 = 0;
const int32_t INDEX_1 = 1;
const int32_t INDEX_2 = 2;
const int32_t INDEX_3 = 3;
const int32_t PARAM_COUNT_1 = 1;
const int32_t PARAM_COUNT_2 = 2;
const int32_t PARAM_COUNT_3 = 3;
const int32_t PARAM_COUNT_4 = 4;

IJKPlayerNapiProxy* IJKPlayerNapiRender::ijkPlayerNapiProxy_;
OH_NativeXComponent_Callback IJKPlayerNapiRender::callback_;
std::unordered_map <std::string, IJKPlayerNapiRender* > IJKPlayerNapiRender::ijkPlayerNapiRender_;


napi_env envMessage_;
napi_ref callBackRefMessage_;

struct CallbackContext {
    napi_env env = nullptr;
    napi_ref callbackRef = nullptr;
    int what = 0;
    int arg1=0;
    int arg2=0;
};

void messageCallBack(int what,int arg1,int arg2)
{
    LOGI("napi-->messageCallBack");
    struct CallbackContext* context= new CallbackContext();
    context->env = envMessage_;
    uv_loop_s* loopMessage = nullptr;
    napi_get_uv_event_loop(context->env, &loopMessage);
    if(loopMessage == nullptr){
        LOGI("napi-->loopMessage null");
        return;
    }
    uv_work_t* work = new (std::nothrow) uv_work_t;
    if (work == nullptr) {
        LOGI("napi-->work null");
        return;
    }
    context->what = what;
    context->arg1 = arg1;
    context->arg2 = arg2;
    context->callbackRef=callBackRefMessage_;
    work->data = (void*)context;
    uv_queue_work(
            loopMessage, work, [](uv_work_t* work) {}   ,
            // using callback function back to JS thread
            [](uv_work_t* work, int status) {
                LOGI("napi-->uv_queue_work");
                CallbackContext* context = (CallbackContext*)work->data;
                napi_value callback = nullptr;
                napi_get_reference_value(context->env, context->callbackRef, &callback);
                napi_value what_;
                napi_value arg1_;
                napi_value arg2_;
                napi_value obj_;
                napi_create_string_utf8(context->env, (char*)((std::to_string(context->what)).c_str()), NAPI_AUTO_LENGTH, &what_);
                napi_create_string_utf8(context->env, (char*)((std::to_string(context->arg1)).c_str()), NAPI_AUTO_LENGTH, &arg1_);
                napi_create_string_utf8(context->env, (char*)((std::to_string(context->arg2)).c_str()), NAPI_AUTO_LENGTH, &arg2_);
                napi_value argv[] = {what_,arg1_,arg2_};
                napi_value ret=0;
                napi_call_function(context->env, nullptr, callback, 3, argv, &ret);
                //                napi_delete_reference(context->env, context->callbackRef);
                if (work != nullptr) {
                    delete work;
                }
                delete context;
                LOGI("napi-->uv_queue_work end");
            }
            );
}

void post_event(void * weak_this, int what, int arg1, int arg2) {
    LOGI("napi-->post_event-->what:%d", what);
    messageCallBack(what,arg1,arg2);
}

void setEnvMessage(const napi_env &env){
    envMessage_=env;
}

void setCallBackRefMessage(const napi_ref &callbackRef){
    callBackRefMessage_=callbackRef;
}


std::string IJKPlayerNapiRender::getXComponentId(napi_env env, napi_callback_info info){
    LOGI("napi-->IJKPlayerNapiRender::GetInstance_()->getXComponentId");
    napi_value exportInstance;
    napi_value thisArg;
    napi_status status;
    OH_NativeXComponent *nativeXComponent = nullptr;
    int32_t ret;
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;

    NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &thisArg, NULL));

    status = napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance);
    if (status != napi_ok) {
        return nullptr;
    };

    status = napi_unwrap(env, exportInstance, reinterpret_cast<void**>(&nativeXComponent));
    if (status != napi_ok) {
        return nullptr;
    }

    ret = OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize);
    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        return nullptr;
    }

    std::string id(idStr);
    LOGI("napi-->IJKPlayerNapiRender::GetInstance_()->getXComponentId id:%s",(char*)id.c_str());
    return id;
}

napi_value IJKPlayerNapiRender::setMessageListener(napi_env env, napi_callback_info info)
{
    LOGI("napi-->msg----setMessageListener");
    size_t argc = 1;
    napi_value args[1];
    napi_get_cb_info(env, info, &argc, args, NULL, NULL);
    napi_value width;
    napi_value height;
    napi_value result = 0;
    napi_value callback = args[0];
    napi_ref callBackRefMessage_;
    napi_create_reference(env, callback, 1, &callBackRefMessage_);
    setCallBackRefMessage(callBackRefMessage_);
    setEnvMessage(env);
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->message_loop_callback(post_event);
    return nullptr;
}


napi_value IJKPlayerNapiRender::native_setup(napi_env env, napi_callback_info info)
{
    LOGI("napi-->native_setup");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    LOGI("napi-->native_setup id->%s",(char*)xc_id.c_str());
    OH_NativeXComponent* xcomponent=IJKPlayerNapiRender::GetInstance(xc_id)->getXComponent(xc_id);
    void* nativeWindow=IJKPlayerNapiRender::GetInstance(xc_id)->getNativeWindow(xc_id);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_native_setup(xcomponent, nativeWindow);
    return nullptr;
}

napi_value IJKPlayerNapiRender::setDataSource(napi_env env, napi_callback_info info)
{
    LOGI("napi-->setDataSource");
    size_t argc = PARAM_COUNT_1;
    napi_value args[PARAM_COUNT_1] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string url;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, url);
    LOGI("napi-->setDataSource-->url:%s", (char*)url.c_str());
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    LOGI("napi-->setDataSource end id->%s",(char*)xc_id.c_str());
    OH_NativeXComponent* xcomponent=IJKPlayerNapiRender::GetInstance(xc_id)->getXComponent(xc_id);
    void* nativeWindow=IJKPlayerNapiRender::GetInstance(xc_id)->getNativeWindow(xc_id);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_native_setup(xcomponent, nativeWindow);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_setDataSource((char*)url.c_str());
    return nullptr;
}

napi_value IJKPlayerNapiRender::setOption(napi_env env, napi_callback_info info)
{
    LOGI("napi-->setOption");
    size_t argc = PARAM_COUNT_3;
    napi_value args[PARAM_COUNT_3] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string category;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, category);
    std::string key;
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, key);
    std::string value;
    NapiUtil::JsValueToString(env, args[INDEX_2], STR_DEFAULT_SIZE, value);
    LOGI("napi-->setOption-->category:%d,key:%s,value:%s", NapiUtil::StringToInt(category), (char*)key.c_str(), (char*)value.c_str());
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_setOption(NapiUtil::StringToInt(category), (char*)key.c_str(), (char*)value.c_str());
    return nullptr;
}


napi_value IJKPlayerNapiRender::setOptionLong(napi_env env, napi_callback_info info)
{
    LOGI("napi-->setOptionLong");
    size_t argc = PARAM_COUNT_3;
    napi_value args[PARAM_COUNT_3] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string category;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, category);
    std::string key;
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, key);
    std::string value;
    NapiUtil::JsValueToString(env, args[INDEX_2], STR_DEFAULT_SIZE, value);
    LOGI("napi-->setOptionLong-->category:%d,key:%s,value:%s", NapiUtil::StringToInt(category), (char*)key.c_str(), (char*)value.c_str());
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_setOptionLong(NapiUtil::StringToInt(category), (char*)key.c_str(), NapiUtil::StringToInt(value));
    return nullptr;
}


napi_value IJKPlayerNapiRender::setVolume(napi_env env, napi_callback_info info)
{
    LOGI("napi-->setVolume");
    size_t argc = PARAM_COUNT_2;
    napi_value args[PARAM_COUNT_2] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string leftVolume;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, leftVolume);
    std::string rightVolume;
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, rightVolume);
    LOGI("napi-->setVolume-->leftVolume:%s,rightVolume:%s",(char*)leftVolume.c_str(), (char*)rightVolume.c_str());
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_setVolume(NapiUtil::StringToFloat(leftVolume),NapiUtil::StringToFloat(rightVolume));
    return nullptr;
}

napi_value IJKPlayerNapiRender::prepareAsync(napi_env env, napi_callback_info info)
{
    LOGI("napi-->prepareAsync");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_prepareAsync();
    return nullptr;
}

napi_value IJKPlayerNapiRender::start(napi_env env, napi_callback_info info)
{
    LOGI("napi-->start");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_start();
    return nullptr;
}

napi_value IJKPlayerNapiRender::stop(napi_env env, napi_callback_info info)
{
    LOGI("napi-->stop");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_stop();
    return nullptr;
}

napi_value IJKPlayerNapiRender::pause(napi_env env, napi_callback_info info)
{
    LOGI("napi-->pause");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_pause();
    return nullptr;
}


napi_value IJKPlayerNapiRender::reset(napi_env env, napi_callback_info info)
{
    LOGI("napi-->pause");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_reset();
    return nullptr;
}

napi_value IJKPlayerNapiRender::release(napi_env env, napi_callback_info info)
{
    LOGI("napi-->pause");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_release();
    return nullptr;
}


napi_value IJKPlayerNapiRender::getDuration(napi_env env, napi_callback_info info)
{
    LOGI("napi-->getDuration");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    int duration= IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_getDuration();
    return NapiUtil::SetNapiCallInt32(env,duration);
}

napi_value IJKPlayerNapiRender::getCurrentPosition(napi_env env, napi_callback_info info)
{
    LOGI("napi-->getCurrentPosition");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    int currentPosition= IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_getCurrentPosition();
    return NapiUtil::SetNapiCallInt32(env,currentPosition);
}

napi_value IJKPlayerNapiRender::seekTo(napi_env env, napi_callback_info info)
{
    LOGI("napi-->seekTo");
    size_t argc = PARAM_COUNT_1;
    napi_value args[PARAM_COUNT_1] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string msec;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, msec);
    LOGI("napi-->seekTo-->msec:%d", NapiUtil::StringToInt(msec));
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_seekTo (NapiUtil::StringToInt(msec));
    return nullptr;
}

napi_value IJKPlayerNapiRender::isPlaying(napi_env env, napi_callback_info info)
{
    LOGI("napi-->isPlaying");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    return NapiUtil::SetNapiCallBool(env, IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_isPlaying());
}

napi_value IJKPlayerNapiRender::setPropertyFloat(napi_env env, napi_callback_info info)
{
    LOGI("napi-->setPropertyFloat");
    size_t argc = PARAM_COUNT_2;
    napi_value args[PARAM_COUNT_2] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string id;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, id);
    std::string value;
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, value);
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->ijkMediaPlayer_setPropertyFloat(NapiUtil::StringToInt(id),NapiUtil::StringToFloat(value));
    return nullptr;
}

napi_value IJKPlayerNapiRender::getPropertyFloat(napi_env env, napi_callback_info info)
{
    LOGI("napi-->getPropertyFloat");
    size_t argc = PARAM_COUNT_2;
    napi_value args[PARAM_COUNT_2] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string id;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, id);
    std::string value;
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, value);
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    float result= IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->ijkMediaPlayer_getPropertyFloat(NapiUtil::StringToInt(id),NapiUtil::StringToFloat(value));
    napi_value napi_result;
    napi_create_string_utf8(env, (char*)((std::to_string(result)).c_str()), NAPI_AUTO_LENGTH, &napi_result);
    return napi_result;
}

napi_value IJKPlayerNapiRender::setPropertyLong(napi_env env, napi_callback_info info)
{
    LOGI("napi-->setPropertyLong");
    size_t argc = PARAM_COUNT_2;
    napi_value args[PARAM_COUNT_2] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string id;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, id);
    std::string value;
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, value);
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->ijkMediaPlayer_setPropertyLong(NapiUtil::StringToInt(id),NapiUtil::StringToLong(value));
    return nullptr;
}


napi_value IJKPlayerNapiRender::getPropertyLong(napi_env env, napi_callback_info info)
{
    LOGI("napi-->getPropertyLong");
    size_t argc = PARAM_COUNT_2;
    napi_value args[PARAM_COUNT_2] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string id;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, id);
    std::string value;
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, value);
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    long result=IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->ijkMediaPlayer_getPropertyLong(NapiUtil::StringToInt(id),NapiUtil::StringToLong(value));
    napi_value napi_result;
    napi_create_string_utf8(env, (char*)((std::to_string(result)).c_str()), NAPI_AUTO_LENGTH, &napi_result);
    return napi_result;
}

napi_value IJKPlayerNapiRender::getAudioSessionId(napi_env env, napi_callback_info info)
{
    LOGI("napi-->getAudioSessionId");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    int getAudioSessionId=IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_getAudioSessionId();
    return NapiUtil::SetNapiCallInt32(env,getAudioSessionId);
}

napi_value IJKPlayerNapiRender::setLoopCount(napi_env env, napi_callback_info info)
{
    LOGI("napi-->setLoopCount");
    size_t argc = PARAM_COUNT_1;
    napi_value args[PARAM_COUNT_1] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string loop_count;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, loop_count);
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_setLoopCount(NapiUtil::StringToInt(loop_count));
    return nullptr;
}

napi_value IJKPlayerNapiRender::getLoopCount(napi_env env, napi_callback_info info)
{
    LOGI("napi-->getLoopCount");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    int loop_count=IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_getLoopCount();
    return NapiUtil::SetNapiCallInt32(env,loop_count);
}

napi_value IJKPlayerNapiRender::getVideoCodecInfo(napi_env env, napi_callback_info info)
{
    LOGI("napi-->getVideoCodecInfo");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    char* result = IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_getVideoCodecInfo();
    LOGI("napi-->getVideoCodecInfo result:%s",result);
    napi_value napi_result;
    napi_create_string_utf8(env, result, NAPI_AUTO_LENGTH, &napi_result);
    return napi_result;
}

napi_value IJKPlayerNapiRender::getAudioCodecInfo(napi_env env, napi_callback_info info)
{
    LOGI("napi-->getAudioCodecInfo");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    char* result = IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_getAudioCodecInfo();
    napi_value napi_result;
    napi_create_string_utf8(env, result, NAPI_AUTO_LENGTH, &napi_result);
    return napi_result;
}

napi_value IJKPlayerNapiRender::setStreamSelected(napi_env env, napi_callback_info info)
{
    LOGI("napi-->setStreamSelected");
    size_t argc = PARAM_COUNT_2;
    napi_value args[PARAM_COUNT_2] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    std::string stream;
    NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, stream);
    std::string select;
    NapiUtil::JsValueToString(env, args[INDEX_1], STR_DEFAULT_SIZE, select);
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->ijkMediaPlayer_setStreamSelected(NapiUtil::StringToInt(stream),NapiUtil::StringToBool(select));
    return nullptr;
}

napi_value IJKPlayerNapiRender::getMediaMeta(napi_env env, napi_callback_info info)
{
    LOGI("napi-->getMediaMeta");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    HashMap map = IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_getMediaMeta();
    HashMapIterator iterator = hashmap_iterator(map);
    std::string result="";
    while (hashmap_hasNext(iterator)) {
        iterator = hashmap_next(iterator);
        LOGI("napi-->getMediaMeta { key: %s, value: %s, hashcode: %d }\n",
                (STRING)iterator->entry->key, (STRING)iterator->entry->value, iterator->hashCode);
        result.append("key:");
        result.append((STRING)iterator->entry->key);
        result.append(",");
        result.append("value:");
        result.append((STRING)iterator->entry->value);
        result.append(";");
    }
    hashmap_delete(map);
    napi_value napi_result;
    napi_create_string_utf8(env, (char*)(result.c_str()), NAPI_AUTO_LENGTH, &napi_result);
    return napi_result;
}

napi_value IJKPlayerNapiRender::nativeOpenlog(napi_env env, napi_callback_info info)
{
    LOGI("napi-->nativeOpenlog");
    std::string xc_id = IJKPlayerNapiRender::getXComponentId(env,info);
    IJKPlayerNapiRender::GetInstance(xc_id)->ijkPlayerNapiProxy_->IjkMediaPlayer_native_openlog();
    return nullptr;
}




/////////////////////////////XComponent////////////////////////////////

void IJKPlayerNapiRender::SetXComponentAndNativeWindow(std::string& id, OH_NativeXComponent* component,void* window)
{
    LOGI("napi-->IJKPlayerNapiRender::SetXComponentAndNativeWindow");
    if (nativeXComponentMap_.find(id) == nativeXComponentMap_.end()) {
        nativeXComponentMap_[id] = component;
    } else {
        if (nativeXComponentMap_[id] != component) {
            nativeXComponentMap_[id] = component;
        }
    }
    if (nativeWindowMap_.find(id) == nativeWindowMap_.end()) {
        nativeWindowMap_[id] = window;
    } else {
        if (nativeWindowMap_[id] != window) {
            nativeWindowMap_[id] = window;
        }
    }
}

OH_NativeXComponent* IJKPlayerNapiRender::getXComponent(std::string& id)
{
    LOGI("napi-->IJKPlayerNapiRender::getXComponent");
    if (nativeXComponentMap_.find(id) == nativeXComponentMap_.end()){
        LOGI("napi-->IJKPlayerNapiRender::getXComponent null");
        return nullptr;
    } else {
        LOGI("napi-->IJKPlayerNapiRender::getXComponent success");
        return nativeXComponentMap_[id];
    }
}


void* IJKPlayerNapiRender::getNativeWindow(std::string& id)
{
    LOGI("napi-->IJKPlayerNapiRender::getNativeWindow");
    if (nativeWindowMap_.find(id) == nativeWindowMap_.end()) {
        LOGI("napi-->IJKPlayerNapiRender::getNativeWindow null");
        return nullptr;
    } else {
        LOGI("napi-->IJKPlayerNapiRender::getNativeWindow success");
        return nativeWindowMap_[id];
    }
}


void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window)
{
    LOGI("napi-->OnSurfaceCreatedCB");
    int32_t ret;
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { };
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        return;
    }
    LOGI("napi-->OnSurfaceCreatedCB-->success");

    std::string id(idStr);
    auto render = IJKPlayerNapiRender::GetInstance(id);
    render->OnSurfaceCreated(component, window);
    render->SetXComponentAndNativeWindow(id,component,window);
}

void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window)
{
    LOGI("napi-->OnSurfaceChangedCB");
    int32_t ret;
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { };
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        return;
    }
    std::string id(idStr);
    auto render = IJKPlayerNapiRender::GetInstance(id);
    render->OnSurfaceChanged(component, window);
}

void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window)
{
    LOGI("napi-->OnSurfaceDestroyedCB");
    int32_t ret;
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { };
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        return;
    }
    std::string id(idStr);
    auto render = IJKPlayerNapiRender::GetInstance(id);
    render->OnSurfaceDestroyed(component, window);
}

void DispatchTouchEventCB(OH_NativeXComponent* component, void* window)
{
    LOGI("napi-->DispatchTouchEventCB");
    int32_t ret;
    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { };
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
    if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        return;
    }
    std::string id(idStr);
    auto render = IJKPlayerNapiRender::GetInstance(id);
    render->DispatchTouchEvent(component, window);
}

void IJKPlayerNapiRender::OnSurfaceCreated(OH_NativeXComponent* component, void* window)
{
    LOGI("napi-->OnSurfaceCreated");
    int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
    if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        LOGI("napi-->OnSurfaceCreated-->success");
    }

}

void IJKPlayerNapiRender::OnSurfaceChanged(OH_NativeXComponent* component, void* window)
{
    LOGI("napi-->OnSurfaceChanged");
}

void IJKPlayerNapiRender::OnSurfaceDestroyed(OH_NativeXComponent* component, void* window)
{
    LOGI("napi-->OnSurfaceDestroyed");
}

void IJKPlayerNapiRender::DispatchTouchEvent(OH_NativeXComponent* component, void* window)
{
    LOGI("napi-->DispatchTouchEvent");
    int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_);
    if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        LOGI("napi-->DispatchTouchEvent-->success");
    }
}


IJKPlayerNapiRender::IJKPlayerNapiRender(std::string& id) : xcomponentId_(id), component_(nullptr)
{
    LOGI("IJKPlayerNapiRender::IJKPlayerNapiRender");
    ijkPlayerNapiProxy_ = new IJKPlayerNapiProxy(id);
    auto renderCallback = IJKPlayerNapiRender::GetNXComponentCallback();
    renderCallback->OnSurfaceCreated = OnSurfaceCreatedCB;
    renderCallback->OnSurfaceChanged = OnSurfaceChangedCB;
    renderCallback->OnSurfaceDestroyed = OnSurfaceDestroyedCB;
    renderCallback->DispatchTouchEvent = DispatchTouchEventCB;
}


IJKPlayerNapiRender* IJKPlayerNapiRender::GetInstance(std::string& id)
{
    LOGI("napi-->IJKPlayerNapiRender::GetInstance");
    if (ijkPlayerNapiRender_.find(id) == ijkPlayerNapiRender_.end()) {
        LOGI("napi-->IJKPlayerNapiRender::GetInstance create object");
        IJKPlayerNapiRender* instance = new IJKPlayerNapiRender(id);
        ijkPlayerNapiRender_[id] = instance;
        return instance;
    } else {
        LOGI("napi-->IJKPlayerNapiRender::GetInstance return");
        return ijkPlayerNapiRender_[id];
    }
}


OH_NativeXComponent_Callback* IJKPlayerNapiRender::GetNXComponentCallback()
{
    LOGI("IJKPlayerNapiRender::GetNXComponentCallback");
    return &IJKPlayerNapiRender::callback_;
}

void IJKPlayerNapiRender::SetNativeXComponent(OH_NativeXComponent* component)
{
    LOGI("IJKPlayerNapiRender::SetNativeXComponent");
    component_ = component;
    OH_NativeXComponent_RegisterCallback(component_, &IJKPlayerNapiRender::callback_);
}


napi_value IJKPlayerNapiRender::Export(napi_env env, napi_value exports)
{
    LOGI("IJKPlayerNapiRender::Export");
    napi_property_descriptor desc[] = {
        DECLARE_NAPI_FUNCTION("_setDataSource", IJKPlayerNapiRender::setDataSource),
        DECLARE_NAPI_FUNCTION("_setOption", IJKPlayerNapiRender::setOption),
        DECLARE_NAPI_FUNCTION("_setOptionLong", IJKPlayerNapiRender::setOptionLong),
        DECLARE_NAPI_FUNCTION("_prepareAsync", IJKPlayerNapiRender::prepareAsync),
        DECLARE_NAPI_FUNCTION("_start", IJKPlayerNapiRender::start),
        DECLARE_NAPI_FUNCTION("_stop", IJKPlayerNapiRender::stop),
        DECLARE_NAPI_FUNCTION("_pause", IJKPlayerNapiRender::pause),
        DECLARE_NAPI_FUNCTION("_reset", IJKPlayerNapiRender::reset),
        DECLARE_NAPI_FUNCTION("_release", IJKPlayerNapiRender::release),
        DECLARE_NAPI_FUNCTION("_seekTo", IJKPlayerNapiRender::seekTo),
        DECLARE_NAPI_FUNCTION("_isPlaying", IJKPlayerNapiRender::isPlaying),
        DECLARE_NAPI_FUNCTION("_setMessageListener", IJKPlayerNapiRender::setMessageListener),
        DECLARE_NAPI_FUNCTION("_getDuration", IJKPlayerNapiRender::getDuration),
        DECLARE_NAPI_FUNCTION("_getCurrentPosition", IJKPlayerNapiRender::getCurrentPosition),
        DECLARE_NAPI_FUNCTION("_setPropertyFloat", IJKPlayerNapiRender::setPropertyFloat),
        DECLARE_NAPI_FUNCTION("_getPropertyFloat", IJKPlayerNapiRender::getPropertyFloat),
        DECLARE_NAPI_FUNCTION("_setPropertyLong", IJKPlayerNapiRender::setPropertyLong),
        DECLARE_NAPI_FUNCTION("_getPropertyLong", IJKPlayerNapiRender::getPropertyLong),
        DECLARE_NAPI_FUNCTION("_getAudioSessionId", IJKPlayerNapiRender::getAudioSessionId),
        DECLARE_NAPI_FUNCTION("_setVolume", IJKPlayerNapiRender::setVolume),
        DECLARE_NAPI_FUNCTION("_setLoopCount", IJKPlayerNapiRender::setLoopCount),
        DECLARE_NAPI_FUNCTION("_getLoopCount", IJKPlayerNapiRender::getLoopCount),
        DECLARE_NAPI_FUNCTION("_getVideoCodecInfo", IJKPlayerNapiRender::getVideoCodecInfo),
        DECLARE_NAPI_FUNCTION("_getAudioCodecInfo", IJKPlayerNapiRender::getAudioCodecInfo),
        DECLARE_NAPI_FUNCTION("_setStreamSelected", IJKPlayerNapiRender::setStreamSelected),
        DECLARE_NAPI_FUNCTION("_getMediaMeta", IJKPlayerNapiRender::getMediaMeta),
        DECLARE_NAPI_FUNCTION("_nativeOpenlog", IJKPlayerNapiRender::nativeOpenlog),
        DECLARE_NAPI_FUNCTION("_native_setup", IJKPlayerNapiRender::native_setup),
    };
    NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
    return exports;
}
